#include "spaceship.h"
#include "frametiming.h"
#include "textrenderer.h"
#include "input.h"
#include "utils.h"
#include <iostream>

Spaceship::Spaceship(string name, string spaceshipModel, SceneManager *sceneMgr)
	: mSceneMgr(sceneMgr),
	mSpeed(0, 0, 0), mAcceleration(0, 0, 0), maxAcceleration(150),
	mRotationSpeed(0, 0, 0), mRotationAcceleration(0, 0, 0), maxRotationAcceleration(4),
	maxRotationSpeed(3), maxSpeed(500)
{
	initialize();
	setupScene(name, spaceshipModel);
}

Spaceship::~Spaceship()
{
	mSceneMgr->getRootSceneNode()->removeAndDestroyChild(mSpaceshipNode->getName());
	delete mSpaceshipEntity;
	delete mSpaceshipNode;
}


void Spaceship::initialize()
{
}

void Spaceship::setupScene(string name, string spaceshipModel)
{
	mSpaceshipEntity = mSceneMgr->createEntity( name, spaceshipModel );
	mSpaceshipEntity->setCastShadows(true);
	mSpaceshipNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();
	mSpaceshipNode->attachObject( mSpaceshipEntity );
}

Vector3 Spaceship::getSpeed()
{
	return mSpeed;
}


void Spaceship::setSpeed(Vector3 vector)
{
	mSpeed = vector;
}

Vector3 Spaceship::getAcceleration()
{
	return mAcceleration;
}

void Spaceship::setAcceleration(Vector3 vector)
{
	mAcceleration = vector;
}

void Spaceship::doPhysics()
{
	// 1. Rotamos la nave
	mRotationSpeed = mRotationSpeed + FrameTiming::getSingleton()->timeSinceLastFrame() * mRotationAcceleration;
	mSpaceshipNode->pitch(Radian(mRotationSpeed.x * FrameTiming::getSingleton()->timeSinceLastFrame()));
	mSpaceshipNode->yaw(Radian(mRotationSpeed.y * FrameTiming::getSingleton()->timeSinceLastFrame()));
	mSpaceshipNode->roll(Radian(mRotationSpeed.z * FrameTiming::getSingleton()->timeSinceLastFrame()));
	
	// 2. Movemos la nave
	bool modeAutomatic = InputHandler::getSingleton()->getModeAutomatic();
	Vector3 accelInParent = mSpaceshipNode->getOrientation() * mAcceleration;
	
	mSpeed = mSpeed + FrameTiming::getSingleton()->timeSinceLastFrame() * accelInParent;
	mSpaceshipNode->translate(mSpeed * FrameTiming::getSingleton()->timeSinceLastFrame());
}

void MySpaceship::doActions(vector<Action> currentEvents)
{
	mAcceleration = Vector3(0,0,0);
	mRotationAcceleration = Vector3(0,0,0);
	
	bool modeAutomatic = InputHandler::getSingleton()->getModeAutomatic();
	bool modePowerSteering = InputHandler::getSingleton()->getModePowerSteering();
	bool pitch = false, turn = false, roll = false;
	bool go_x = false, go_y = false, go_z = false;
	Vector3 mSpeedChild = mSpaceshipNode->getOrientation().Inverse() * mSpeed;
	
	for(vector<Action>::iterator it = currentEvents.begin(); it != currentEvents.end(); it++)
	{
		switch (*it)
		{
			case ACTION_PITCH_UP:
				pitch = true;
 				if(modeAutomatic == false)
					mRotationAcceleration.x = maxRotationAcceleration;
				else
					Utils::autoRotate(Utils::X, maxRotationAcceleration, maxRotationSpeed, mRotationSpeed, mRotationAcceleration);
				break;
			case ACTION_PITCH_DOWN:
				pitch = true;
				if(modeAutomatic == false)
					mRotationAcceleration.x = -maxRotationAcceleration;
				else
					Utils::autoRotate(Utils::X, maxRotationAcceleration, -maxRotationSpeed, mRotationSpeed, mRotationAcceleration);
				break;
			case ACTION_TURN_LEFT:
				turn = true;
				if(modeAutomatic == false)
					mRotationAcceleration.y = maxRotationAcceleration;
				else
					Utils::autoRotate(Utils::Y, maxRotationAcceleration, maxRotationSpeed, mRotationSpeed, mRotationAcceleration);
				break;
			case ACTION_TURN_RIGHT:
				turn = true;
				if(modeAutomatic == false)
					mRotationAcceleration.y = -maxRotationAcceleration;
				else
					Utils::autoRotate(Utils::Y, maxRotationAcceleration, -maxRotationSpeed, mRotationSpeed, mRotationAcceleration);
				break;
			case ACTION_ROLL_LEFT:
				roll = true;
				if(modeAutomatic == false)
					mRotationAcceleration.z = -maxRotationAcceleration;
				else
					Utils::autoRotate(Utils::Z, maxRotationAcceleration, -maxRotationSpeed, mRotationSpeed, mRotationAcceleration);
				break;
			case ACTION_ROLL_RIGHT:
				roll = true;
				if(modeAutomatic == false)
					mRotationAcceleration.z = maxRotationAcceleration;
				else
					Utils::autoRotate(Utils::Z, maxRotationAcceleration, maxRotationSpeed, mRotationSpeed, mRotationAcceleration);
				break;
			case ACTION_GO_UP:
				go_y = true;
				if(modeAutomatic == false)
					mAcceleration.y = maxAcceleration;
				else
					Utils::autoRotate(Utils::Y, maxAcceleration, maxSpeed, mSpeedChild, mAcceleration);
				break;
			case ACTION_GO_DOWN:
				go_y = true;
				if(modeAutomatic == false)
					mAcceleration.y = -maxAcceleration;
				else
					Utils::autoRotate(Utils::Y, maxAcceleration, -maxSpeed, mSpeedChild, mAcceleration);
				break;
			case ACTION_GO_LEFT:
				go_x = true;
				if(modeAutomatic == false)
					mAcceleration.y = maxAcceleration;
				else
					Utils::autoRotate(Utils::X, maxAcceleration, maxSpeed, mSpeedChild, mAcceleration);
				break;
			case ACTION_GO_RIGHT:
				go_x = true;
				if(modeAutomatic == false)
					mAcceleration.y = -maxAcceleration;
				else
					Utils::autoRotate(Utils::X, maxAcceleration, -maxSpeed, mSpeedChild, mAcceleration);
				break;
			case ACTION_GO_FORWARD:
				go_z = true;
				if(modeAutomatic == false)
					mAcceleration.z = maxAcceleration;
				else
					Utils::autoRotate(Utils::Z, maxAcceleration, maxSpeed, mSpeedChild, mAcceleration);
				break;
			case ACTION_GO_BACKWARD:
				go_z = true;
				if(modeAutomatic == false)
					mAcceleration.z = -maxAcceleration;
				else
					Utils::autoRotate(Utils::Z, maxAcceleration, -maxSpeed, mSpeedChild, mAcceleration);
				break;
		}
	}
	
	if(modeAutomatic == true)
	{
		if(pitch == false)
			Utils::autoRotate(Utils::X, maxRotationAcceleration, 0, mRotationSpeed, mRotationAcceleration);
		if(turn == false)
			Utils::autoRotate(Utils::Y, maxRotationAcceleration, 0, mRotationSpeed, mRotationAcceleration);
		if(roll == false)
			Utils::autoRotate(Utils::Z, maxRotationAcceleration, 0, mRotationSpeed, mRotationAcceleration);
		if(go_x == false)
		{
			Utils::autoRotate(Utils::X, maxAcceleration, 0, mSpeedChild, mAcceleration);
		}
		if(go_y== false)
		{
			Utils::autoRotate(Utils::Y, maxAcceleration, 0, mSpeedChild, mAcceleration);
		}
		if(go_z == false)
		{
			Utils::autoRotate(Utils::Z, maxAcceleration, 0, mSpeedChild, mAcceleration);
		}
	}
}

MySpaceship::MySpaceship(string name, string spaceshipModel, SceneManager *sceneMgr)
	: Spaceship(name, spaceshipModel, sceneMgr)
{
	setupScene(name, spaceshipModel);
	TextRenderer::getSingleton().addTextBox("speedDisplay", "", 500, 10, 100, 20, Ogre::ColourValue::Green);
	FrameTiming::getSingleton()->addTimer("updateSpeedDisplay", 500000, updateSpeedDisplay, (void*)this);
	updateSpeedDisplay((void*)this);
}


void MySpaceship::setupScene(string name, string spaceshipModel)
{
	// Posicionamos la cámara
	mCamera = mSceneMgr->createCamera(mSpaceshipEntity->getName() + "Cam");
	mCamera->setPosition(Vector3(0, 200, -300));
	mCamera->lookAt(Vector3(0,0,0));
	mCamera->setNearClipDistance(1);
	
	mCameraNode = mSpaceshipNode->createChildSceneNode();
	mCameraNode->attachObject(mCamera);
	
// 	mShieldEntity = mSceneMgr->createEntity( "myShield", "bola.mesh" );
// 	mShieldEntity->setMaterialName("spaceship/shield");
// 	mShieldNode = mSpaceshipNode->createChildSceneNode();
// 	mShieldNode->attachObject(mShieldEntity);
// 	mShieldNode->scale(100, 100, 100);
	
	NameValuePairList pairList;
	pairList["numberOfChains"] = "2";
	pairList["maxElements"] = "80";
	RibbonTrail* trail = static_cast<RibbonTrail*>(
	mSceneMgr->createMovableObject("1", "RibbonTrail", &pairList));
	trail->setMaterialName("LightRibbonTrail");
	trail->setTrailLength(400);
	mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(trail);
	trail->setInitialColour(0, 1.0, 0.8, 0);
	trail->setColourChange(0, 0.5, 0.5, 0.5, 0.5);
	trail->setInitialWidth(0, 10);
	trail->setInitialColour(1, 1.0, 0.8, 0);
	trail->setColourChange(1, 0.5, 0.5, 0.5, 0.5);
	trail->setInitialWidth(1, 10);
	
	SceneNode* trail1 = mSpaceshipNode->createChildSceneNode();
	SceneNode* trail2 = mSpaceshipNode->createChildSceneNode();
	
	trail1->setPosition(72, -20, -60);
	trail2->setPosition(-85, -20, -60);
	
	trail->addNode(trail1);
	trail->addNode(trail2);
}

void MySpaceship::initialize()
{
	
}

Camera* MySpaceship::getCamera()
{
	return mCamera;
}

void MySpaceship::updateSpeedDisplay()
{
	ostringstream ostream;
	
	ostream << "Speed: " << (unsigned long int)mSpeed.length();
	TextRenderer::getSingleton().setText("speedDisplay", ostream.str());
}

void MySpaceship::updateSpeedDisplay(void *spaceship)
{
	MySpaceship* mySpaceship = reinterpret_cast<MySpaceship*>(spaceship);
	mySpaceship->updateSpeedDisplay();
}

